#include <windows.h>
#include <stdio.h>
#include <tchar.h>
#include "log.h"
#include "tracelog.h"
#include "db_log.h"
//syb specific
#include <ctpublic.h>

//------------------------------------------------------------------------
//------------------------- SYBASE ---------------------------------------
//------------------------------------------------------------------------



typedef CS_RETCODE (FAR PASCAL *__srv_msg_callback)(CS_CONTEXT*ctx, CS_CONNECTION*con, CS_SERVERMSG*srvmsg);

typedef CS_RETCODE (CS_PUBLIC *__ct_callback)(CS_CONTEXT *context,CS_CONNECTION *connection,CS_INT action,CS_INT type,CS_VOID *func);



HINSTANCE		 _syb_lib=NULL;
__srv_msg_callback old_srv_msg_callback=NULL;
__ct_callback _ct_callback=NULL;


bool _load_syb(){
	if(!_syb_lib)_syb_lib=LoadLibrary(L"libct.dll");
	if(!_syb_lib){
		tracelog_add(1, L"tracelog.dll", L"Can't load Sybase client library libct.dll.");
		return false;
	}
	if(!_ct_callback)_ct_callback=(__ct_callback)GetProcAddress(_syb_lib,"ct_callback");
	if(!_ct_callback){
		tracelog_add(1, L"tracelog.dll", L"Can't find \"ct_callback\" function in libct.dll.");
		return false;
	}
	return true;
}



CS_RETCODE CS_PUBLIC ex_servermsg_cb(CS_CONTEXT*ctx, CS_CONNECTION*con, CS_SERVERMSG*srvmsg){
	_db_message_handler((srvmsg->severity == 0 || srvmsg->severity == 10)?false:true,srvmsg->msgnumber,srvmsg->text,srvmsg->proc,srvmsg->line);
	if ( old_srv_msg_callback ) return old_srv_msg_callback(ctx, con, srvmsg);
	return CS_SUCCEED;
}


bool install_message_callback_syb(void*_con){
	CS_CONNECTION *con=(CS_CONNECTION *)_con;
	if (!_load_syb())return false;
	//get old callback message
	if ( _ct_callback(NULL, con, CS_GET, CS_SERVERMSG_CB, (void*)&old_srv_msg_callback) != CS_SUCCEED ) {
		tracelog_add(1, L"tracelog.dll", L"install_message_callback: ct_callback(CS_GET) failed.");
		return false;
	}
	//set the new one
	if( _ct_callback(NULL, con, CS_SET, CS_SERVERMSG_CB, (void*)ex_servermsg_cb) != CS_SUCCEED) {
		tracelog_add(1, L"tracelog.dll", L"install_message_callback: ct_callback(CS_SET) failed.");
		old_srv_msg_callback = NULL;
		return false;
	}
	return true;
}

bool remove_message_callback_syb(void*_con){
	CS_CONNECTION *con=(CS_CONNECTION *)_con;
   //return the old cb
	if(con == NULL)return true;
	if(old_srv_msg_callback == NULL)return true;
	if( _ct_callback(NULL, con, CS_SET, CS_SERVERMSG_CB, (void*)old_srv_msg_callback) != CS_SUCCEED ) {
		tracelog_add(1, L"tracelog.dll", L"remove_message_callback: ct_callback(CS_SET) failed.");
		return false;
	}
	old_srv_msg_callback = NULL;
	return true;
}

